#if !DISABLE_HYBRIDCLR
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using Newtonsoft.Json;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using UnityEditorInternal;
using cframework_xlua;

public static class HotUpdateCodeTool
{
    static string dllResourcesOutputPath = $"Assets/HyBridCLR_Cache/{HotUpdateDllMgr.hotupdate_code_dir}";


    public static string ToRelativeAssetPath(string s)
    {
        return s.Substring(s.IndexOf("Assets/"));
    }


    public static void BuildHotUpdateDll(string outputPath, string hotupdateResConfigPath, int minAppVersion, string monodisPath)
    {
        string appVersionPath = outputPath + "/app_version.txt";
        string versionInfoPath = outputPath + "/" + "version_info";

        CommonUtil.CreateDir(dllResourcesOutputPath);
        BuildHotUpdateDll(dllResourcesOutputPath, hotupdateResConfigPath, versionInfoPath, appVersionPath, minAppVersion);
    }


    public static void BuildHotUpdateBundle(string hotupdateResConfigPath, string outputPath, string last_build_dll_path, string monodisPath)
    {
        BuildHotUpdateDllBundle(hotupdateResConfigPath, outputPath, last_build_dll_path, HotUpdateDllMgr.bundle_name);
    }

    public static void BuildHotUpdateDllBundle(string hotupdateResConfigPath, string outputPath, string lastBuildDllPath, string bundleName)
    {
        string[] srcFilePaths = System.IO.Directory.GetFiles(dllResourcesOutputPath, "*", SearchOption.AllDirectories);



        CommonUtil.Delete(outputPath);
        CommonUtil.CreateDir(outputPath);

        List<string> resPaths = new List<string>();


        foreach (var filePath in srcFilePaths)
        {
            if (filePath.EndsWith(".meta"))
            {
                continue;
            }

            var a = filePath.Replace("\\", "/");

            a = ToRelativeAssetPath(a);

            resPaths.Add(a);
        }

        var ss = AssetDatabase.LoadAssetAtPath<TextAsset>(hotupdateResConfigPath);
        var rr = Newtonsoft.Json.JsonConvert.DeserializeObject<string[]>(ss.text);

        string dir = System.IO.Path.GetDirectoryName(hotupdateResConfigPath);

        foreach (var e in rr)
        {
            if(string.IsNullOrEmpty(e)) continue;

            var d = System.IO.Path.GetRelativePath(System.IO.Path.GetDirectoryName(Application.dataPath), System.IO.Path.GetFullPath(dir + "/" + e));

            if (System.IO.Directory.Exists(d))
            {
                string[] guids = AssetDatabase.FindAssets("*", new string[] { d });

                foreach (var g in guids)
                {
                    string p = AssetDatabase.GUIDToAssetPath(g);

                    if (p.EndsWith(".cs"))
                    {
                        continue;
                    }

                    Debug.LogError("test " +  p + "  " + e);
                    resPaths.Add(p);
                }
            }
            else if (System.IO.File.Exists(d))
            {
                resPaths.Add(d);
            }
        }

        List<AssetBundleBuild> abs = new List<AssetBundleBuild>();
        AssetBundleBuild notSceneAb = new AssetBundleBuild
        {
            assetBundleName = bundleName,
            assetNames = resPaths.ToArray(),
        };
        abs.Add(notSceneAb);

        AssetBundleManifest manifest = BuildPipeline.BuildAssetBundles(outputPath, abs.ToArray(), BuildAssetBundleOptions.None, EditorUserBuildSettings.activeBuildTarget);
        if (manifest == null)
        {
            throw new System.Exception("BuildPipeline.BuildAssetBundles failed");
        }

        CommonUtil.Copy(dllResourcesOutputPath + $"/{HotUpdateDllMgr.config_file_name}", outputPath + $"/{HotUpdateDllMgr.config_file_name}");

        //if (!string.IsNullOrEmpty(lastBuildDllPath))
        //{
        //    CommonUtil.Delete(lastBuildDllPath);
        //    CommonUtil.CreateDir(lastBuildDllPath);


        //    foreach (var filePath in srcFilePaths)
        //    {
        //        if (filePath.EndsWith(".meta"))
        //        {
        //            continue;
        //        }

        //        CommonUtil.Copy(filePath, lastBuildDllPath + "/" + System.IO.Path.GetFileName(filePath));
        //    }
        //}
    }


    //public static void CopyInAppDll(string outputPath, string inAppDllOutoutPath, string appVersionPath, int minAppVersion)
    //{
    //    string srcPath = SettingsUtil.GetAssembliesPostIl2CppStripDir(EditorUserBuildSettings.activeBuildTarget);



    //    string lastInappDllDir = inAppDllOutoutPath;
    //    CommonUtil.CreateDir(lastInappDllDir);

    //    {
    //        string[] oldDllFilePaths = System.IO.Directory.GetFiles(lastInappDllDir, "*", SearchOption.AllDirectories);
    //        foreach (var filePath in oldDllFilePaths)
    //        {
    //            CommonUtil.Delete(filePath);
    //        }

    //        string[] srcDllFilePaths = System.IO.Directory.GetFiles(srcPath, "*.dll", SearchOption.AllDirectories);
    //        foreach (var filePath in srcDllFilePaths)
    //        {
    //            string fileName = System.IO.Path.GetFileName(filePath);

    //            string destPath = lastInappDllDir + "/" + fileName;
    //            CommonUtil.Copy(filePath, destPath);
    //        }
    //    }




    //    bool allSame = true;

    //    string il2cppInfoDirPath = outputPath;






    //    CommonUtil.CreateDir(il2cppInfoDirPath);


    //    HashSet<string> srcMethodBridgeFileNames = new HashSet<string>();
    //    HashSet<string> destMethodBridgeFileNames = new HashSet<string>();


    //    Dictionary<string, string> needCompareFileMap = new Dictionary<string, string>();

    //    {
    //        string srcLinkFilePath = $"{Application.dataPath}/{SettingsUtil.HybridCLRSettings.outputLinkFile}"; ;
    //        string destLinkFilePath = il2cppInfoDirPath + "/" + System.IO.Path.GetFileName(srcLinkFilePath);
    //        destLinkFilePath = destLinkFilePath.Replace('\\', '/');
    //        needCompareFileMap.Add(srcLinkFilePath, destLinkFilePath);
    //    }

    //    if (allSame)
    //    {
    //        foreach (var entry in needCompareFileMap)
    //        {
    //            var hash0 = MD5Hash.GetMD5HashFromFile(entry.Key);
    //            if (!CommonUtil.Exists(entry.Value))
    //            {
    //                allSame = false;
    //                break;
    //            }

    //            var hash1 = MD5Hash.GetMD5HashFromFile(entry.Value);
    //            if (hash0 != hash1)
    //            {
    //                allSame = false;
    //                break;
    //            }
    //        }
    //    }

    //    {
    //        string[] oldFilePaths = System.IO.Directory.GetFiles(il2cppInfoDirPath, "*", SearchOption.AllDirectories);
    //        foreach (var filePath in oldFilePaths)
    //        {
    //            CommonUtil.Delete(filePath);
    //        }

    //        foreach (var entry in needCompareFileMap)
    //        {
    //            CommonUtil.Copy(entry.Key, entry.Value);
    //        }
    //    }


    //    string versionFilePath = appVersionPath;
    //    if (!allSame || !CommonUtil.Exists(versionFilePath) || minAppVersion != 0)
    //    {
    //        if (minAppVersion <= 0)
    //        {
    //            minAppVersion = AppManager.GetAppInfo().hotupdate_version;
    //        }

    //        CommonUtil.stringToFile(versionFilePath, minAppVersion.ToString());
    //    }
    //}

    private static void BuildHotUpdateDll(string outputPath, string hotupdateResConfigPath, string latest_hotupdate_dll_dir, string appVersionPath, int minAppVersion)
    {
        BuildTarget target = EditorUserBuildSettings.activeBuildTarget;

        Directory.CreateDirectory(outputPath);




        string appVersionFilePath = appVersionPath;

        //string minAppVersionStr = CommonUtil.fileToString(appVersionFilePath);

        //bool allSame = true;
        //Debug.Log("test allsame 1: " + allSame + " | " + minAppVersionStr + " | " + string.IsNullOrEmpty(minAppVersionStr) + " | " + CommonUtil.Exists(appVersionFilePath) + " | " + minAppVersion);

        //if (minAppVersion == 0)
        //{
        //    if (string.IsNullOrEmpty(minAppVersionStr))
        //    {
        //        minAppVersion = AppManager.GetAppInfo().hotupdate_version;
        //    }
        //    else
        //    {
        //        if (allSame)
        //        {
        //            minAppVersion = int.Parse(minAppVersionStr);
        //        }
        //        else
        //        {
        //            minAppVersion = AppManager.GetAppInfo().hotupdate_version;
        //            CommonUtil.stringToFile(appVersionFilePath, minAppVersion.ToString());
        //        }
        //    }
        //}
        //else if (minAppVersion < 0)
        //{
        //    minAppVersion = AppManager.GetAppInfo().hotupdate_version;
        //}

        List<string> resPaths = new List<string>();
        var ss = AssetDatabase.LoadAssetAtPath<TextAsset>(hotupdateResConfigPath);
        var rr = Newtonsoft.Json.JsonConvert.DeserializeObject<string[]>(ss.text);

        string dir = System.IO.Path.GetDirectoryName(hotupdateResConfigPath);

        foreach (var e in rr)
        {
            string d = dir + "/" + e;
            if (System.IO.Directory.Exists(d))
            {
                string[] guids = AssetDatabase.FindAssets("*", new string[] { d });
                foreach (var g in guids)
                {
                    string p = AssetDatabase.GUIDToAssetPath(g);
                    if (p.EndsWith(".cs"))
                    {
                        continue;
                    }

                    resPaths.Add(p);
                }
            }
            else if (System.IO.File.Exists(d))
            {
                resPaths.Add(d);
            }
        }

        string[] dependences = AssetDatabase.GetDependencies(resPaths.ToArray(), true);
        HashSet<string> scriptPathSet = new HashSet<string>();
        foreach (var p in dependences)
        {
            if (p.EndsWith(".cs"))
            {
                scriptPathSet.Add(p);
            }
        }

        minAppVersion = AddressableTool.GenerateMinAppVersion(scriptPathSet, minAppVersion, latest_hotupdate_dll_dir);
        CommonUtil.stringToFile(appVersionFilePath, minAppVersion.ToString());

        HotUpdateCodeInfo info = new HotUpdateCodeInfo();
        info.hotupdate_version = AppManager.GetAppInfo().hotupdate_version;
        info.min_app_hotupdate_version = minAppVersion;
        info.build_time = System.DateTime.Now.ToString("u");
        info.build_timestamp = CommonUtil.GetTimeStamp();



        string configStr = JsonConvert.SerializeObject(info, Formatting.Indented);
        CommonUtil.stringToFile(outputPath + "/" + HotUpdateDllMgr.config_file_name, configStr);

        AssetDatabase.Refresh();
    }

    public static void Copy(string outputPath, string hotupdateResConfigPath)
    {
        BuildTarget target = EditorUserBuildSettings.activeBuildTarget;

        Directory.CreateDirectory(outputPath);






        var ss = AssetDatabase.LoadAssetAtPath<TextAsset>(hotupdateResConfigPath);
        var rr = Newtonsoft.Json.JsonConvert.DeserializeObject<string[]>(ss.text);

        string dir = System.IO.Path.GetDirectoryName(hotupdateResConfigPath).Replace("\\", "/");

        foreach (var e in rr)
        {
            if(string.IsNullOrEmpty(e))
            {
                continue;
            }

            string d = dir + "/" + e;
            if (System.IO.Directory.Exists(d))
            {
                //d = System.IO.Path.GetFullPath(System.IO.Path.GetDirectoryName(Application.dataPath) + "/" + d);

                d = System.IO.Path.GetDirectoryName(Application.dataPath) + "/" + d;
                d = System.IO.Path.GetFullPath(d).Replace("\\", "/");

                d = d.Replace(System.IO.Path.GetDirectoryName(Application.dataPath).Replace("\\", "/") + "/", "");


                
                string[] guids = AssetDatabase.FindAssets("*.lua", new string[] { d });
                foreach (var g in guids)
                {
                    string p = AssetDatabase.GUIDToAssetPath(g).Replace("\\", "/");

                    var destPath = outputPath + "/" + p.Replace(d.Replace("\\", "/") + "/", "");
                    var createDir = System.IO.Path.GetDirectoryName(destPath);


                    System.IO.Directory.CreateDirectory(createDir);
                    System.IO.File.Copy(p, destPath, true);
                }
            }
        }

        AssetDatabase.Refresh();
    }
}

#endif